<!-- HTML header for doxygen 1.8.6-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<title>OpenCV: Capture Gray code pattern tutorial</title>
<link href="../../opencv.ico" rel="shortcut icon" type="image/x-icon" />
<link href="../../tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../dynsections.js"></script>
<script type="text/javascript" src="../../tutorial-utils.js"></script>
<link href="../../search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../search/searchdata.js"></script>
<script type="text/javascript" src="../../search/search.js"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    extensions: ["tex2jax.js", "TeX/AMSmath.js", "TeX/AMSsymbols.js"],
    jax: ["input/TeX","output/HTML-CSS"],
});
//<![CDATA[
MathJax.Hub.Config(
{
  TeX: {
      Macros: {
          matTT: [ "\\[ \\left|\\begin{array}{ccc} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{array}\\right| \\]", 9],
          fork: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ \\end{array} \\right.", 4],
          forkthree: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ \\end{array} \\right.", 6],
          forkfour: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ #7 & \\mbox{#8}\\\\ \\end{array} \\right.", 8],
          vecthree: ["\\begin{bmatrix} #1\\\\ #2\\\\ #3 \\end{bmatrix}", 3],
          vecthreethree: ["\\begin{bmatrix} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{bmatrix}", 9],
          cameramatrix: ["#1 = \\begin{bmatrix} f_x & 0 & c_x\\\\ 0 & f_y & c_y\\\\ 0 & 0 & 1 \\end{bmatrix}", 1],
          distcoeffs: ["(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6 [, s_1, s_2, s_3, s_4[, \\tau_x, \\tau_y]]]]) \\text{ of 4, 5, 8, 12 or 14 elements}"],
          distcoeffsfisheye: ["(k_1, k_2, k_3, k_4)"],
          hdotsfor: ["\\dots", 1],
          mathbbm: ["\\mathbb{#1}", 1],
          bordermatrix: ["\\matrix{#1}", 1]
      }
  }
}
);
//]]>
</script><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js"></script>
<link href="../../doxygen.css" rel="stylesheet" type="text/css" />
<link href="../../stylesheet.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<!--#include virtual="/google-search.html"-->
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="../../opencv-logo-small.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">OpenCV
   &#160;<span id="projectnumber">4.5.2</span>
   </div>
   <div id="projectbrief">Open Source Computer Vision</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "../../search",false,'Search');
</script>
<script type="text/javascript" src="../../menudata.js"></script>
<script type="text/javascript" src="../../menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('../../',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="../../d3/d81/tutorial_contrib_root.html">Tutorials for contrib modules</a></li><li class="navelem"><a class="el" href="../../d3/d81/tutorial_structured_light.html">Structured Light tutorials</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">Capture Gray code pattern tutorial </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><h2>Goal </h2>
<p>In this tutorial you will learn how to use the <em>GrayCodePattern</em> class to:</p>
<ul>
<li>Generate a Gray code pattern.</li>
<li>Project the Gray code pattern.</li>
<li>Capture the projected Gray code pattern.</li>
</ul>
<p>It is important to underline that <em>GrayCodePattern</em> class actually implements the 3DUNDERWORLD algorithm described in <a class="el" href="../../d0/de3/citelist.html#CITEREF_UNDERWORLD">[109]</a> , which is based on a stereo approach: we need to capture the projected pattern at the same time from two different views if we want to reconstruct the 3D model of the scanned object. Thus, an acquisition set consists of the images captured by each camera for each image in the pattern sequence.</p>
<h2>Code </h2>
<div class="fragment"><div class="line"><span class="comment">/*M///////////////////////////////////////////////////////////////////////////////////////</span></div><div class="line"><span class="comment"> //</span></div><div class="line"><span class="comment"> //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.</span></div><div class="line"><span class="comment"> //</span></div><div class="line"><span class="comment"> //  By downloading, copying, installing or using the software you agree to this license.</span></div><div class="line"><span class="comment"> //  If you do not agree to this license, do not download, install,</span></div><div class="line"><span class="comment"> //  copy or use the software.</span></div><div class="line"><span class="comment"> //</span></div><div class="line"><span class="comment"> //</span></div><div class="line"><span class="comment"> //                           License Agreement</span></div><div class="line"><span class="comment"> //                For Open Source Computer Vision Library</span></div><div class="line"><span class="comment"> //</span></div><div class="line"><span class="comment"> // Copyright (C) 2015, OpenCV Foundation, all rights reserved.</span></div><div class="line"><span class="comment"> // Third party copyrights are property of their respective owners.</span></div><div class="line"><span class="comment"> //</span></div><div class="line"><span class="comment"> // Redistribution and use in source and binary forms, with or without modification,</span></div><div class="line"><span class="comment"> // are permitted provided that the following conditions are met:</span></div><div class="line"><span class="comment"> //</span></div><div class="line"><span class="comment"> //   * Redistribution&#39;s of source code must retain the above copyright notice,</span></div><div class="line"><span class="comment"> //     this list of conditions and the following disclaimer.</span></div><div class="line"><span class="comment"> //</span></div><div class="line"><span class="comment"> //   * Redistribution&#39;s in binary form must reproduce the above copyright notice,</span></div><div class="line"><span class="comment"> //     this list of conditions and the following disclaimer in the documentation</span></div><div class="line"><span class="comment"> //     and/or other materials provided with the distribution.</span></div><div class="line"><span class="comment"> //</span></div><div class="line"><span class="comment"> //   * The name of the copyright holders may not be used to endorse or promote products</span></div><div class="line"><span class="comment"> //     derived from this software without specific prior written permission.</span></div><div class="line"><span class="comment"> //</span></div><div class="line"><span class="comment"> // This software is provided by the copyright holders and contributors &quot;as is&quot; and</span></div><div class="line"><span class="comment"> // any express or implied warranties, including, but not limited to, the implied</span></div><div class="line"><span class="comment"> // warranties of merchantability and fitness for a particular purpose are disclaimed.</span></div><div class="line"><span class="comment"> // In no event shall the Intel Corporation or contributors be liable for any direct,</span></div><div class="line"><span class="comment"> // indirect, incidental, special, exemplary, or consequential damages</span></div><div class="line"><span class="comment"> // (including, but not limited to, procurement of substitute goods or services;</span></div><div class="line"><span class="comment"> // loss of use, data, or profits; or business interruption) however caused</span></div><div class="line"><span class="comment"> // and on any theory of liability, whether in contract, strict liability,</span></div><div class="line"><span class="comment"> // or tort (including negligence or otherwise) arising in any way out of</span></div><div class="line"><span class="comment"> // the use of this software, even if advised of the possibility of such damage.</span></div><div class="line"><span class="comment"> //</span></div><div class="line"><span class="comment"> //M*/</span></div><div class="line"></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="../../d1/d4f/imgproc_2include_2opencv2_2imgproc_8hpp.html">opencv2/imgproc.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="../../d4/dd5/highgui_8hpp.html">opencv2/highgui.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="../../d3/d23/structured__light_8hpp.html">opencv2/structured_light.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;iostream&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;stdio.h&gt;</span></div><div class="line"></div><div class="line"><span class="keyword">using namespace </span><a class="code" href="../../d2/d75/namespacecv.html">cv</a>;</div><div class="line"><span class="keyword">using namespace </span>std;</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">char</span>* keys =</div><div class="line">{ <span class="stringliteral">&quot;{@path | | Path of the folder where the captured pattern images will be save }&quot;</span></div><div class="line">     <span class="stringliteral">&quot;{@proj_width      | | Projector width            }&quot;</span></div><div class="line">     <span class="stringliteral">&quot;{@proj_height     | | Projector height           }&quot;</span> };</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> help()</div><div class="line">{</div><div class="line">    cout &lt;&lt; <span class="stringliteral">&quot;\nThis example shows how to use the \&quot;Structured Light module\&quot; to acquire a graycode pattern&quot;</span></div><div class="line">         <span class="stringliteral">&quot;\nCall (with the two cams connected):\n&quot;</span></div><div class="line">         <span class="stringliteral">&quot;./example_structured_light_cap_pattern &lt;path&gt; &lt;proj_width&gt; &lt;proj_height&gt; \n&quot;</span></div><div class="line">         &lt;&lt; endl;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">int</span> main( <span class="keywordtype">int</span> argc, <span class="keywordtype">char</span>** argv )</div><div class="line">{</div><div class="line"></div><div class="line">  <a class="code" href="../../d3/d4d/structcv_1_1structured__light_1_1GrayCodePattern_1_1Params.html">structured_light::GrayCodePattern::Params</a> <a class="code" href="../../d1/dae/namespacecv_1_1gapi_1_1ie.html#a3ab1729bcaf2d08e30dd2bc645410908">params</a>;</div><div class="line"></div><div class="line">  <a class="code" href="../../d0/d2e/classcv_1_1CommandLineParser.html">CommandLineParser</a> parser( argc, argv, keys );</div><div class="line">  <a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a> path = parser.get&lt;<a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a>&gt;( 0 );</div><div class="line">  params.<a class="code" href="../../d3/d4d/structcv_1_1structured__light_1_1GrayCodePattern_1_1Params.html#afeaf367767fcb43529a4fa5b9c9309af">width</a> = parser.get&lt;<span class="keywordtype">int</span>&gt;( 1 );</div><div class="line">  params.<a class="code" href="../../d3/d4d/structcv_1_1structured__light_1_1GrayCodePattern_1_1Params.html#a06c9109b5a1ec886e270984b68e480e4">height</a> = parser.get&lt;<span class="keywordtype">int</span>&gt;( 2 );</div><div class="line"></div><div class="line">  <span class="keywordflow">if</span>( path.empty() || params.<a class="code" href="../../d3/d4d/structcv_1_1structured__light_1_1GrayCodePattern_1_1Params.html#afeaf367767fcb43529a4fa5b9c9309af">width</a> &lt; 1 || params.<a class="code" href="../../d3/d4d/structcv_1_1structured__light_1_1GrayCodePattern_1_1Params.html#a06c9109b5a1ec886e270984b68e480e4">height</a> &lt; 1 )</div><div class="line">  {</div><div class="line">    help();</div><div class="line">    <span class="keywordflow">return</span> -1;</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="comment">// Set up GraycodePattern with params</span></div><div class="line">  <a class="code" href="../../dc/d84/group__core__basic.html#ga6395ca871a678020c4a31fadf7e8cc63">Ptr&lt;structured_light::GrayCodePattern&gt;</a> graycode = <a class="code" href="../../d1/dec/classcv_1_1structured__light_1_1GrayCodePattern.html#a1f724251afc61fc2d6f7451721cb90fe">structured_light::GrayCodePattern::create</a>( params );</div><div class="line"></div><div class="line">  <span class="comment">// Storage for pattern</span></div><div class="line">  vector&lt;Mat&gt; pattern;</div><div class="line">  graycode-&gt;generate( pattern );</div><div class="line"></div><div class="line">  cout &lt;&lt; pattern.size() &lt;&lt; <span class="stringliteral">&quot; pattern images + 2 images for shadows mask computation to acquire with both cameras&quot;</span></div><div class="line">         &lt;&lt; endl;</div><div class="line"></div><div class="line">  <span class="comment">// Generate the all-white and all-black images needed for shadows mask computation</span></div><div class="line">  <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> white;</div><div class="line">  <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> black;</div><div class="line">  graycode-&gt;getImagesForShadowMasks( black, white );</div><div class="line"></div><div class="line">  pattern.push_back( white );</div><div class="line">  pattern.push_back( black );</div><div class="line"></div><div class="line">  <span class="comment">// Setting pattern window on second monitor (the projector&#39;s one)</span></div><div class="line">  <a class="code" href="../../d7/dfc/group__highgui.html#ga5afdf8410934fd099df85c75b2e0888b">namedWindow</a>( <span class="stringliteral">&quot;Pattern Window&quot;</span>, <a class="code" href="../../d0/d90/group__highgui__window__flags.html#ggabf7d2c5625bc59ac130287f925557ac3a29e45c5af696f73ce5e153601e5ca0f1">WINDOW_NORMAL</a> );</div><div class="line">  <a class="code" href="../../d7/dfc/group__highgui.html#ga9e80e080f7ef33f897e415358aee7f7e">resizeWindow</a>( <span class="stringliteral">&quot;Pattern Window&quot;</span>, params.<a class="code" href="../../d3/d4d/structcv_1_1structured__light_1_1GrayCodePattern_1_1Params.html#afeaf367767fcb43529a4fa5b9c9309af">width</a>, params.<a class="code" href="../../d3/d4d/structcv_1_1structured__light_1_1GrayCodePattern_1_1Params.html#a06c9109b5a1ec886e270984b68e480e4">height</a> );</div><div class="line">  <a class="code" href="../../d7/dfc/group__highgui.html#ga8d86b207f7211250dbe6e28f76307ffb">moveWindow</a>( <span class="stringliteral">&quot;Pattern Window&quot;</span>, params.<a class="code" href="../../d3/d4d/structcv_1_1structured__light_1_1GrayCodePattern_1_1Params.html#afeaf367767fcb43529a4fa5b9c9309af">width</a> + 316, -20 );</div><div class="line">  <a class="code" href="../../d7/dfc/group__highgui.html#ga66e4a6db4d4e06148bcdfe0d70a5df27">setWindowProperty</a>( <span class="stringliteral">&quot;Pattern Window&quot;</span>, <a class="code" href="../../d0/d90/group__highgui__window__flags.html#ggaeedf4023e777f896ba6b9ffb156f57b8a3b6a89b0daf2149dab93f9c6ab99fcc8">WND_PROP_FULLSCREEN</a>, <a class="code" href="../../d0/d90/group__highgui__window__flags.html#ggabf7d2c5625bc59ac130287f925557ac3a78bc64121f612562bbb2fa23d316e84e">WINDOW_FULLSCREEN</a> );</div><div class="line"></div><div class="line">  <span class="comment">// Open camera number 1, using libgphoto2</span></div><div class="line">  <a class="code" href="../../d8/dfe/classcv_1_1VideoCapture.html">VideoCapture</a> cap1( <a class="code" href="../../d4/d15/group__videoio__flags__base.html#gga023786be1ee68a9105bf2e48c700294da96c457f30fddf85dc689f940a4c07807">CAP_GPHOTO2</a> );</div><div class="line"></div><div class="line">  <span class="keywordflow">if</span>( !cap1.isOpened() )</div><div class="line">  {</div><div class="line">    <span class="comment">// check if cam1 opened</span></div><div class="line">    cout &lt;&lt; <span class="stringliteral">&quot;cam1 not opened!&quot;</span> &lt;&lt; endl;</div><div class="line">    help();</div><div class="line">    <span class="keywordflow">return</span> -1;</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="comment">// Open camera number 2</span></div><div class="line">  <a class="code" href="../../d8/dfe/classcv_1_1VideoCapture.html">VideoCapture</a> cap2( 1 );</div><div class="line"></div><div class="line">  <span class="keywordflow">if</span>( !cap2.isOpened() )</div><div class="line">  {</div><div class="line">     <span class="comment">// check if cam2 opened</span></div><div class="line">     cout &lt;&lt; <span class="stringliteral">&quot;cam2 not opened!&quot;</span> &lt;&lt; endl;</div><div class="line">     help();</div><div class="line">     <span class="keywordflow">return</span> -1;</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="comment">// Turning off autofocus</span></div><div class="line">  cap1.set( <a class="code" href="../../d4/d15/group__videoio__flags__base.html#ggaeb8dd9c89c10a5c63c139bf7c4f5704da6339d098548d91f438b6f10ee1407c72">CAP_PROP_SETTINGS</a>, 1 );</div><div class="line">  cap2.set( <a class="code" href="../../d4/d15/group__videoio__flags__base.html#ggaeb8dd9c89c10a5c63c139bf7c4f5704da6339d098548d91f438b6f10ee1407c72">CAP_PROP_SETTINGS</a>, 1 );</div><div class="line"></div><div class="line">  <span class="keywordtype">int</span> i = 0;</div><div class="line">  <span class="keywordflow">while</span>( i &lt; (<span class="keywordtype">int</span>) pattern.size() )</div><div class="line">  {</div><div class="line">    cout &lt;&lt; <span class="stringliteral">&quot;Waiting to save image number &quot;</span> &lt;&lt; i + 1 &lt;&lt; endl &lt;&lt; <span class="stringliteral">&quot;Press any key to acquire the photo&quot;</span> &lt;&lt; endl;</div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga453d42fe4cb60e5723281a89973ee563">imshow</a>( <span class="stringliteral">&quot;Pattern Window&quot;</span>, pattern[i] );</div><div class="line"></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> frame1;</div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> frame2;</div><div class="line"></div><div class="line">    cap1 &gt;&gt; frame1;  <span class="comment">// get a new frame from camera 1</span></div><div class="line">    cap2 &gt;&gt; frame2;  <span class="comment">// get a new frame from camera 2</span></div><div class="line"></div><div class="line">    <span class="keywordflow">if</span>( ( frame1.data ) &amp;&amp; ( frame2.data ) )</div><div class="line">    {</div><div class="line"></div><div class="line">      <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> tmp;</div><div class="line">      cout &lt;&lt; <span class="stringliteral">&quot;cam 1 size: &quot;</span> &lt;&lt; <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>( ( <span class="keywordtype">int</span> ) cap1.get( <a class="code" href="../../d4/d15/group__videoio__flags__base.html#ggaeb8dd9c89c10a5c63c139bf7c4f5704dab26d2ba37086662261148e9fe93eecad">CAP_PROP_FRAME_WIDTH</a> ), ( int ) cap1.get( <a class="code" href="../../d4/d15/group__videoio__flags__base.html#ggaeb8dd9c89c10a5c63c139bf7c4f5704dad8b57083fd9bd58e0f94e68a54b42b7e">CAP_PROP_FRAME_HEIGHT</a> ) )</div><div class="line">           &lt;&lt; endl;</div><div class="line"></div><div class="line">      cout &lt;&lt; <span class="stringliteral">&quot;cam 2 size: &quot;</span> &lt;&lt; <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>( ( <span class="keywordtype">int</span> ) cap2.get( <a class="code" href="../../d4/d15/group__videoio__flags__base.html#ggaeb8dd9c89c10a5c63c139bf7c4f5704dab26d2ba37086662261148e9fe93eecad">CAP_PROP_FRAME_WIDTH</a> ), ( int ) cap2.get( <a class="code" href="../../d4/d15/group__videoio__flags__base.html#ggaeb8dd9c89c10a5c63c139bf7c4f5704dad8b57083fd9bd58e0f94e68a54b42b7e">CAP_PROP_FRAME_HEIGHT</a> ) )</div><div class="line">           &lt;&lt; endl;</div><div class="line"></div><div class="line">      cout &lt;&lt; <span class="stringliteral">&quot;zoom cam 1: &quot;</span> &lt;&lt; cap1.get( <a class="code" href="../../d4/d15/group__videoio__flags__base.html#ggaeb8dd9c89c10a5c63c139bf7c4f5704da73f3ec06cf4f9aca1ab7f3b52260fd5e">CAP_PROP_ZOOM</a> ) &lt;&lt; endl &lt;&lt; <span class="stringliteral">&quot;zoom cam 2: &quot;</span> &lt;&lt; cap2.get( <a class="code" href="../../d4/d15/group__videoio__flags__base.html#ggaeb8dd9c89c10a5c63c139bf7c4f5704da73f3ec06cf4f9aca1ab7f3b52260fd5e">CAP_PROP_ZOOM</a> )</div><div class="line">           &lt;&lt; endl;</div><div class="line"></div><div class="line">      cout &lt;&lt; <span class="stringliteral">&quot;focus cam 1: &quot;</span> &lt;&lt; cap1.get( <a class="code" href="../../d4/d15/group__videoio__flags__base.html#ggaeb8dd9c89c10a5c63c139bf7c4f5704da25fe3d87b62a918427d49f3d43aef714">CAP_PROP_FOCUS</a> ) &lt;&lt; endl &lt;&lt; <span class="stringliteral">&quot;focus cam 2: &quot;</span> &lt;&lt; cap2.get( <a class="code" href="../../d4/d15/group__videoio__flags__base.html#ggaeb8dd9c89c10a5c63c139bf7c4f5704da25fe3d87b62a918427d49f3d43aef714">CAP_PROP_FOCUS</a> )</div><div class="line">           &lt;&lt; endl;</div><div class="line"></div><div class="line">      cout &lt;&lt; <span class="stringliteral">&quot;Press enter to save the photo or an other key to re-acquire the photo&quot;</span> &lt;&lt; endl;</div><div class="line"></div><div class="line">      <a class="code" href="../../d7/dfc/group__highgui.html#ga5afdf8410934fd099df85c75b2e0888b">namedWindow</a>( <span class="stringliteral">&quot;cam1&quot;</span>, <a class="code" href="../../d0/d90/group__highgui__window__flags.html#ggabf7d2c5625bc59ac130287f925557ac3a29e45c5af696f73ce5e153601e5ca0f1">WINDOW_NORMAL</a> );</div><div class="line">      <a class="code" href="../../d7/dfc/group__highgui.html#ga9e80e080f7ef33f897e415358aee7f7e">resizeWindow</a>( <span class="stringliteral">&quot;cam1&quot;</span>, 640, 480 );</div><div class="line"></div><div class="line">      <a class="code" href="../../d7/dfc/group__highgui.html#ga5afdf8410934fd099df85c75b2e0888b">namedWindow</a>( <span class="stringliteral">&quot;cam2&quot;</span>, <a class="code" href="../../d0/d90/group__highgui__window__flags.html#ggabf7d2c5625bc59ac130287f925557ac3a29e45c5af696f73ce5e153601e5ca0f1">WINDOW_NORMAL</a> );</div><div class="line">      <a class="code" href="../../d7/dfc/group__highgui.html#ga9e80e080f7ef33f897e415358aee7f7e">resizeWindow</a>( <span class="stringliteral">&quot;cam2&quot;</span>, 640, 480 );</div><div class="line"></div><div class="line">      <span class="comment">// Moving window of cam2 to see the image at the same time with cam1</span></div><div class="line">      <a class="code" href="../../d7/dfc/group__highgui.html#ga8d86b207f7211250dbe6e28f76307ffb">moveWindow</a>( <span class="stringliteral">&quot;cam2&quot;</span>, 640 + 75, 0 );</div><div class="line"></div><div class="line">      <span class="comment">// Resizing images to avoid issues for high resolution images, visualizing them as grayscale</span></div><div class="line">      <a class="code" href="../../da/d54/group__imgproc__transform.html#ga47a974309e9102f5f08231edc7e7529d">resize</a>( frame1, tmp, <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>( 640, 480 ), 0, 0, <a class="code" href="../../da/d54/group__imgproc__transform.html#gga5bb5a1fea74ea38e1a5445ca803ff121ac00f4a8155563cdc23437fc0959da935">INTER_LINEAR_EXACT</a>);</div><div class="line">      <a class="code" href="../../d8/d01/group__imgproc__color__conversions.html#ga397ae87e1288a81d2363b61574eb8cab">cvtColor</a>( tmp, tmp, <a class="code" href="../../d8/d01/group__imgproc__color__conversions.html#gga4e0972be5de079fed4e3a10e24ef5ef0ae50d0c66ee53e974234ac84cf51d1d4e">COLOR_RGB2GRAY</a> );</div><div class="line">      <a class="code" href="../../d7/dfc/group__highgui.html#ga453d42fe4cb60e5723281a89973ee563">imshow</a>( <span class="stringliteral">&quot;cam1&quot;</span>, tmp );</div><div class="line">      <a class="code" href="../../da/d54/group__imgproc__transform.html#ga47a974309e9102f5f08231edc7e7529d">resize</a>( frame2, tmp, <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>( 640, 480 ), 0, 0, <a class="code" href="../../da/d54/group__imgproc__transform.html#gga5bb5a1fea74ea38e1a5445ca803ff121ac00f4a8155563cdc23437fc0959da935">INTER_LINEAR_EXACT</a>);</div><div class="line">      <a class="code" href="../../d8/d01/group__imgproc__color__conversions.html#ga397ae87e1288a81d2363b61574eb8cab">cvtColor</a>( tmp, tmp, <a class="code" href="../../d8/d01/group__imgproc__color__conversions.html#gga4e0972be5de079fed4e3a10e24ef5ef0ae50d0c66ee53e974234ac84cf51d1d4e">COLOR_RGB2GRAY</a> );</div><div class="line">      <a class="code" href="../../d7/dfc/group__highgui.html#ga453d42fe4cb60e5723281a89973ee563">imshow</a>( <span class="stringliteral">&quot;cam2&quot;</span>, tmp );</div><div class="line"></div><div class="line">      <span class="keywordtype">bool</span> save1 = <span class="keyword">false</span>;</div><div class="line">      <span class="keywordtype">bool</span> save2 = <span class="keyword">false</span>;</div><div class="line"></div><div class="line">      <span class="keywordtype">int</span> key = <a class="code" href="../../d7/dfc/group__highgui.html#ga5628525ad33f52eab17feebcfba38bd7">waitKey</a>( 0 );</div><div class="line"></div><div class="line">      <span class="comment">// Pressing enter, it saves the output</span></div><div class="line">      <span class="keywordflow">if</span>( key == 13 )</div><div class="line">      {</div><div class="line">        ostringstream name;</div><div class="line">        name &lt;&lt; i + 1;</div><div class="line"></div><div class="line">        save1 = <a class="code" href="../../d4/da8/group__imgcodecs.html#gabbc7ef1aa2edfaa87772f1202d67e0ce">imwrite</a>( path + <span class="stringliteral">&quot;pattern_cam1_im&quot;</span> + name.str() + <span class="stringliteral">&quot;.png&quot;</span>, frame1 );</div><div class="line">        save2 = <a class="code" href="../../d4/da8/group__imgcodecs.html#gabbc7ef1aa2edfaa87772f1202d67e0ce">imwrite</a>( path + <span class="stringliteral">&quot;pattern_cam2_im&quot;</span> + name.str() + <span class="stringliteral">&quot;.png&quot;</span>, frame2 );</div><div class="line"></div><div class="line">        <span class="keywordflow">if</span>( ( save1 ) &amp;&amp; ( save2 ) )</div><div class="line">        {</div><div class="line">          cout &lt;&lt; <span class="stringliteral">&quot;pattern cam1 and cam2 images number &quot;</span> &lt;&lt; i + 1 &lt;&lt; <span class="stringliteral">&quot; saved&quot;</span> &lt;&lt; endl &lt;&lt; endl;</div><div class="line">          i++;</div><div class="line">        }</div><div class="line">        <span class="keywordflow">else</span></div><div class="line">        {</div><div class="line">          cout &lt;&lt; <span class="stringliteral">&quot;pattern cam1 and cam2 images number &quot;</span> &lt;&lt; i + 1 &lt;&lt; <span class="stringliteral">&quot; NOT saved&quot;</span> &lt;&lt; endl &lt;&lt; endl &lt;&lt; <span class="stringliteral">&quot;Retry, check the path&quot;</span>&lt;&lt; endl &lt;&lt; endl;</div><div class="line">        }</div><div class="line">      }</div><div class="line">      <span class="comment">// Pressing escape, the program closes</span></div><div class="line">      <span class="keywordflow">if</span>( key == 27 )</div><div class="line">      {</div><div class="line">        cout &lt;&lt; <span class="stringliteral">&quot;Closing program&quot;</span> &lt;&lt; endl;</div><div class="line">      }</div><div class="line">    }</div><div class="line">    <span class="keywordflow">else</span></div><div class="line">    {</div><div class="line">      cout &lt;&lt; <span class="stringliteral">&quot;No frame data, waiting for new frame&quot;</span> &lt;&lt; endl;</div><div class="line">    }</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="comment">// the camera will be deinitialized automatically in VideoCapture destructor</span></div><div class="line">  <span class="keywordflow">return</span> 0;</div><div class="line">}</div></div><!-- fragment --><h2>Explanation </h2>
<p>First of all the pattern images to project must be generated. Since the number of images is a function of the projector's resolution, <em>GrayCodePattern</em> class parameters must be set with our projector's width and height. In this way the <em>generate</em> method can be called: it fills a vector of Mat with the computed pattern images:</p>
<div class="fragment"><div class="line"><a class="code" href="../../d4/d41/namespacecv_1_1dynafu.html#afe352b7045bf5f1496c2d8dd2a09a764">structured_light::GrayCodePattern::Params</a> <a class="code" href="../../d1/dae/namespacecv_1_1gapi_1_1ie.html#a3ab1729bcaf2d08e30dd2bc645410908">params</a>;</div><div class="line">  ....</div><div class="line">params.width = parser.get&lt;<span class="keywordtype">int</span>&gt;( 1 );</div><div class="line">params.height = parser.get&lt;<span class="keywordtype">int</span>&gt;( 2 );</div><div class="line">  ....</div><div class="line"><span class="comment">// Set up GraycodePattern with params</span></div><div class="line">Ptr&lt;structured_light::GrayCodePattern&gt; graycode = structured_light::GrayCodePattern::create( params );</div><div class="line"><span class="comment">// Storage for pattern</span></div><div class="line">vector&lt;Mat&gt; pattern;</div><div class="line">graycode-&gt;generate( pattern );</div></div><!-- fragment --><p>For example, using the default projector resolution (1024 x 768), 40 images have to be projected: 20 for regular color pattern (10 images for the columns sequence and 10 for the rows one) and 20 for the color-inverted pattern, where the inverted pattern images are images with the same structure as the original but with inverted colors. This provides an effective method for easily determining the intensity value of each pixel when it is lit (highest value) and when it is not lit (lowest value) during the decoding step.</p>
<p>Subsequently, to identify shadow regions, the regions of two images where the pixels are not lit by projector's light and thus where there is not code information, the 3DUNDERWORLD algorithm computes a shadow mask for the two cameras views, starting from a white and a black images captured by each camera. So two additional images need to be projected and captured with both cameras:</p>
<div class="fragment"><div class="line"><span class="comment">// Generate the all-white and all-black images needed for shadows mask computation</span></div><div class="line">Mat white;</div><div class="line">Mat black;</div><div class="line">graycode-&gt;getImagesForShadowMasks( black, white );</div><div class="line">pattern.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#af4bd5c2cb936dd363816d867aab22a61">push_back</a>( white );</div><div class="line">pattern.push_back( black );</div></div><!-- fragment --><p>Thus, the final projection sequence is projected as follows: first the column and its inverted sequence, then the row and its inverted sequence and finally the white and black images.</p>
<p>Once the pattern images have been generated, they must be projected using the full screen option: the images must fill all the projection area, otherwise the projector full resolution is not exploited, a condition on which is based 3DUNDERWORLD implementation.</p>
<div class="fragment"><div class="line"><span class="comment">// Setting pattern window on second monitor (the projector&#39;s one)</span></div><div class="line"><a class="code" href="../../d7/dfc/group__highgui.html#ga5afdf8410934fd099df85c75b2e0888b">namedWindow</a>( <span class="stringliteral">&quot;Pattern Window&quot;</span>, <a class="code" href="../../d0/d90/group__highgui__window__flags.html#ggabf7d2c5625bc59ac130287f925557ac3a29e45c5af696f73ce5e153601e5ca0f1">WINDOW_NORMAL</a> );</div><div class="line"><a class="code" href="../../d7/dfc/group__highgui.html#ga9e80e080f7ef33f897e415358aee7f7e">resizeWindow</a>( <span class="stringliteral">&quot;Pattern Window&quot;</span>, params.width, params.height );</div><div class="line"><a class="code" href="../../d7/dfc/group__highgui.html#ga8d86b207f7211250dbe6e28f76307ffb">moveWindow</a>( <span class="stringliteral">&quot;Pattern Window&quot;</span>, params.width + 316, -20 );</div><div class="line"><a class="code" href="../../d7/dfc/group__highgui.html#ga66e4a6db4d4e06148bcdfe0d70a5df27">setWindowProperty</a>( <span class="stringliteral">&quot;Pattern Window&quot;</span>, <a class="code" href="../../d0/d90/group__highgui__window__flags.html#ggaeedf4023e777f896ba6b9ffb156f57b8a3b6a89b0daf2149dab93f9c6ab99fcc8">WND_PROP_FULLSCREEN</a>, <a class="code" href="../../d0/d90/group__highgui__window__flags.html#ggabf7d2c5625bc59ac130287f925557ac3a78bc64121f612562bbb2fa23d316e84e">WINDOW_FULLSCREEN</a> );</div></div><!-- fragment --><p>At this point the images can be captured with our digital cameras, using libgphoto2 library, recently included in OpenCV: remember to turn on gPhoto2 option in Cmake.list when building OpenCV. </p><div class="fragment"><div class="line"><span class="comment">// Open camera number 1, using libgphoto2</span></div><div class="line">VideoCapture cap1( <a class="code" href="../../d4/d15/group__videoio__flags__base.html#gga023786be1ee68a9105bf2e48c700294da96c457f30fddf85dc689f940a4c07807">CAP_GPHOTO2</a> );</div><div class="line"><span class="keywordflow">if</span>( !cap1.isOpened() )</div><div class="line">{</div><div class="line">  <span class="comment">// check if cam1 opened</span></div><div class="line">  cout &lt;&lt; <span class="stringliteral">&quot;cam1 not opened!&quot;</span> &lt;&lt; endl;</div><div class="line">  help();</div><div class="line">  <span class="keywordflow">return</span> -1;</div><div class="line">}</div><div class="line"><span class="comment">// Open camera number 2</span></div><div class="line">VideoCapture cap2( 1 );</div><div class="line"><span class="keywordflow">if</span>( !cap2.isOpened() )</div><div class="line">{</div><div class="line">   <span class="comment">// check if cam2 opened</span></div><div class="line">   cout &lt;&lt; <span class="stringliteral">&quot;cam2 not opened!&quot;</span> &lt;&lt; endl;</div><div class="line">   help();</div><div class="line">   <span class="keywordflow">return</span> -1;</div><div class="line">}</div></div><!-- fragment --><p>The two cameras must work at the same resolution and must have autofocus option disabled, maintaining the same focus during all acquisition. The projector can be positioned in the middle of the cameras.</p>
<p>However, before to proceed with pattern acquisition, the cameras must be calibrated. Once the calibration is performed, there should be no movement of the cameras, otherwise a new calibration will be needed.</p>
<p>After having connected the cameras and the projector to the computer, cap_pattern demo can be launched giving as parameters the path where to save the images, and the projector's width and height, taking care to use the same focus and cameras settings of calibration.</p>
<p>At this point, to acquire the images with both cameras, the user can press any key.</p>
<div class="fragment"><div class="line"><span class="comment">// Turning off autofocus</span></div><div class="line">cap1.set( <a class="code" href="../../d4/d15/group__videoio__flags__base.html#ggaeb8dd9c89c10a5c63c139bf7c4f5704da6339d098548d91f438b6f10ee1407c72">CAP_PROP_SETTINGS</a>, 1 );</div><div class="line">cap2.set( <a class="code" href="../../d4/d15/group__videoio__flags__base.html#ggaeb8dd9c89c10a5c63c139bf7c4f5704da6339d098548d91f438b6f10ee1407c72">CAP_PROP_SETTINGS</a>, 1 );</div><div class="line"><span class="keywordtype">int</span> i = 0;</div><div class="line"><span class="keywordflow">while</span>( i &lt; (<span class="keywordtype">int</span>) pattern.size() )</div><div class="line">{</div><div class="line">  cout &lt;&lt; <span class="stringliteral">&quot;Waiting to save image number &quot;</span> &lt;&lt; i + 1 &lt;&lt; endl &lt;&lt; <span class="stringliteral">&quot;Press any key to acquire the photo&quot;</span> &lt;&lt; endl;</div><div class="line">  <a class="code" href="../../d7/dfc/group__highgui.html#ga453d42fe4cb60e5723281a89973ee563">imshow</a>( <span class="stringliteral">&quot;Pattern Window&quot;</span>, pattern[i] );</div><div class="line">  Mat frame1;</div><div class="line">  Mat frame2;</div><div class="line">  cap1 &gt;&gt; frame1;  <span class="comment">// get a new frame from camera 1</span></div><div class="line">  cap2 &gt;&gt; frame2;  <span class="comment">// get a new frame from camera 2</span></div><div class="line">   ...</div><div class="line">}</div></div><!-- fragment --><p>If the captured images are good (the user must take care that the projected pattern is viewed from the two cameras), the user can save them pressing the enter key, otherwise pressing any other key he can take another shot. </p><div class="fragment"><div class="line"><span class="comment">// Pressing enter, it saves the output</span></div><div class="line"><span class="keywordflow">if</span>( key == 13 )</div><div class="line">{</div><div class="line">  ostringstream name;</div><div class="line">  name &lt;&lt; i + 1;</div><div class="line">  save1 = <a class="code" href="../../d4/da8/group__imgcodecs.html#gabbc7ef1aa2edfaa87772f1202d67e0ce">imwrite</a>( path + <span class="stringliteral">&quot;pattern_cam1_im&quot;</span> + name.str() + <span class="stringliteral">&quot;.png&quot;</span>, frame1 );</div><div class="line">  save2 = <a class="code" href="../../d4/da8/group__imgcodecs.html#gabbc7ef1aa2edfaa87772f1202d67e0ce">imwrite</a>( path + <span class="stringliteral">&quot;pattern_cam2_im&quot;</span> + name.str() + <span class="stringliteral">&quot;.png&quot;</span>, frame2 );</div><div class="line">  <span class="keywordflow">if</span>( ( save1 ) &amp;&amp; ( save2 ) )</div><div class="line">  {</div><div class="line">    cout &lt;&lt; <span class="stringliteral">&quot;pattern cam1 and cam2 images number &quot;</span> &lt;&lt; i + 1 &lt;&lt; <span class="stringliteral">&quot; saved&quot;</span> &lt;&lt; endl &lt;&lt; endl;</div><div class="line">    i++;</div><div class="line">  }</div><div class="line">  <span class="keywordflow">else</span></div><div class="line">  {</div><div class="line">    cout &lt;&lt; <span class="stringliteral">&quot;pattern cam1 and cam2 images number &quot;</span> &lt;&lt; i + 1 &lt;&lt; <span class="stringliteral">&quot; NOT saved&quot;</span> &lt;&lt; endl &lt;&lt; endl &lt;&lt; <span class="stringliteral">&quot;Retry, check the path&quot;</span>&lt;&lt; endl &lt;&lt; endl;</div><div class="line">  }</div><div class="line">}</div></div><!-- fragment --><p>The acquistion ends when all the pattern images have saved for both cameras. Then the user can reconstruct the 3D model of the captured scene using the <em>decode</em> method of <em>GrayCodePattern</em> class (see next tutorial). </p>
</div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.6-->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Apr 2 2021 11:36:39 for OpenCV by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="../../doxygen.png" alt="doxygen"/>
</a> 1.8.13
</small></address>
<script type="text/javascript">
//<![CDATA[
addTutorialsButtons();
//]]>
</script>
</body>
</html>
